package auth

import (
	"strconv"

	"github.com/casbin/casbin/v2"
	"github.com/casbin/casbin/v2/model"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"gorm.io/gorm"
)

type AuthService struct {
	enforcer *casbin.Enforcer
	db       *gorm.DB
}

var (
	AuthInstance *AuthService
)

func NewAuthService(db *gorm.DB) error {
	adapter, err := gormadapter.NewAdapterByDB(db)
	if err != nil {
		return err
	}

	m, err := model.NewModelFromFile("internal/auth/casbin_model.conf")
	if err != nil {
		return err
	}

	e, err := casbin.NewEnforcer(m, adapter)
	if err != nil {
		return err
	}

	err = e.LoadPolicy()
	if err != nil {
		return err
	}

	AuthInstance = &AuthService{enforcer: e, db: db}
	return nil
}

// 通过用户名查询其所在部门
func (s *AuthService) GetDeptsByUsername(username string) ([]uint, error) {
	depts, err := s.enforcer.GetRolesForUser(username)
	if err != nil {
		return nil, err
	}

	deptIDs := make([]uint, 0, len(depts))
	for _, dept := range depts {
		deptID, err := strconv.ParseUint(dept, 10, 64)
		if err != nil {
			return nil, err
		}
		deptIDs = append(deptIDs, uint(deptID))
	}
	return deptIDs, nil
}

// 通过部门查询其所属用户
func (s *AuthService) GetUsersByDeptId(id uint) ([]string, error) {
	users, err := s.enforcer.GetUsersForRole(strconv.Itoa(int(id)))
	if err != nil {
		return nil, err
	}

	return users, nil
}

// 通过部门查询其所有的文件夹
func (s *AuthService) GetDeptFoldersByID(id uint) ([]string, error) {
	permissions, err := s.enforcer.GetPermissionsForUser(strconv.Itoa(int(id)))
	if err != nil {
		return nil, err
	}

	folders := make([]string, 0, len(permissions))
	for _, permission := range permissions {
		folders = append(folders, permission[1])
	}
	return folders, nil
}

// 删除用户所有的部门权限
func (s *AuthService) RemoveUserAllDept(username string) (bool, error) {
	return s.enforcer.DeleteRolesForUser(username)
}

// 删除此用户所属的部门权限
func (s *AuthService) RemoveUserFromDept(username string, deptId uint) (bool, error) {
	return s.enforcer.DeleteRoleForUser(username, strconv.Itoa(int(deptId)))
}

// 删除此用户所拥有的文件权限
func (s *AuthService) RemoveUserFilePermission(username string, file, action string) (bool, error) {
	return s.enforcer.DeletePermissionForUser(username, file, action)
}

// 删除此部门所拥有的文件权限
func (s *AuthService) RemoveDeptFilePermission(deptId uint, file, action string) (bool, error) {
	return s.enforcer.DeletePermissionForUser(strconv.Itoa(int(deptId)), file, action)
}

// 检查用户是否拥有文件或目录的权限
func (s *AuthService) CheckUserPermission(username string, path, action string) bool {
	ok, _ := s.enforcer.Enforce(username, path, action)
	return ok
}

// 检查部门是否拥有文件或目录的权限
func (s *AuthService) CheckDeptPermission(deptId uint, path, action string) bool {
	ok, _ := s.enforcer.Enforce(strconv.Itoa(int(deptId)), path, action)
	return ok
}

// 添加用户到部门
func (s *AuthService) AddUserToDept(username string, deptId uint) (bool, error) {
	return s.enforcer.AddRoleForUser(username, strconv.Itoa(int(deptId)))
}

// 修改添加文件权限的方法
func (s *AuthService) AddFilePermission(userOrDeptId uint, path, action string) (bool, error) {
	// 使用正则表达式来表示路径及其子路径
	return s.enforcer.AddPolicy(strconv.Itoa(int(userOrDeptId)), path, action)
}

// 删除文件权限
func (s *AuthService) RemoveFilePermission(DeptId uint, path, action string) (bool, error) {
	return s.enforcer.RemovePolicy(strconv.Itoa(int(DeptId)), path, action)
}

func (s *AuthService) CheckPermission(sub, obj, act string) (bool, error) {
	return s.enforcer.Enforce(sub, obj, act)
}

func (s *AuthService) AddPolicy(sub, obj, act string) (bool, error) {
	return s.enforcer.AddPolicy(sub, obj, act)
}

func (s *AuthService) AddGroupingPolicy(sub, role string) (bool, error) {
	return s.enforcer.AddGroupingPolicy(sub, role)
}

func (s *AuthService) RemovePolicy(sub, obj, act string) (bool, error) {
	return s.enforcer.RemovePolicy(sub, obj, act)
}

func (s *AuthService) RemoveGroupingPolicy(sub, role string) (bool, error) {
	return s.enforcer.RemoveGroupingPolicy(sub, role)
}

func (s *AuthService) GetActionForDeptAndPath(deptId uint, path string) ([]string, error) {
	policies, err := s.enforcer.GetPolicy()
	if err != nil {
		return nil, err
	}

	// 过滤出符合条件的策略规则
	var actions []string
	for _, policy := range policies {
		if s.CheckDeptPermission(deptId, path, policy[2]) {
			actions = append(actions, policy[2])
		}
	}

	return actions, nil
}
